package columnar;

import java.io.*;

import global.*;
import bufmgr.*;
import diskmgr.*;
import heap.*;


public class TupleScan implements GlobalConst{
	
	private static short REC_LEN_STRING = 160;
	private static short REC_LEN_INT = 4;

	private Columnarfile  _cf;
	private Scan[] _hfScans;
	private int _numCols = 0;
	

	public TupleScan(Columnarfile cf)
	    throws InvalidTupleSizeException,
		   IOException
	{
		_cf = cf;
		_numCols = cf.NumberOfColumns();
		
		_hfScans = new Scan[_numCols];
		
		for(int i = 0; i<_numCols;i++)
		{
			_hfScans[i] = new Scan(_cf.ColumnArray()[i]);
		}
		
	}

  /** Retrieve the next tuple in a sequential scan
   *
   * @exception InvalidTupleSizeException Invalid tuple size
   * @exception IOException I/O errors
   *
   * @param tid Tuple ID of the tuple
   * @return the Tuple
 * @throws InvalidTypeException 
   */
	public Tuple getNext(TID tid)
		    throws InvalidTupleSizeException,
			   IOException, FieldNumberOutOfBoundException, InvalidTypeException
	{
		Tuple tuple = null, temp = null;
		AttrType[] typeTuple = new AttrType[_numCols];
		short[] attrLen = new short[_numCols];
		
		for(int i = 0;i<_numCols;i++)
			switch(_cf.getAttrTypes()[i].attrType)
			{
				case AttrType.attrInteger:
					typeTuple[i] = new AttrType(AttrType.attrInteger);
					attrLen[i] = REC_LEN_INT;
				break;
				case AttrType.attrString:
					typeTuple[i] = new AttrType(AttrType.attrString);
					attrLen[i] = REC_LEN_STRING;
				break;
			}

		tuple = new Tuple();
		tuple.setHdr((short)_numCols, typeTuple, attrLen);

		for(int i = 0; i<_numCols;i++)
		{
			temp = _hfScans[i].getNext(tid.recordIDs[i]);
			
			if(temp == null)
				return null;
				
			AttrType[] typeTemp = new AttrType[1];
			
			switch(_cf.getAttrTypes()[i].attrType)
			{
				case AttrType.attrInteger:
		            typeTemp[0] = new AttrType(AttrType.attrInteger);
		            temp.setHdr((short)1, typeTemp, new short[]{REC_LEN_INT});

		            int intVal = temp.getIntFld(1);
					tuple.setIntFld(i+1, intVal);
					break;
				case AttrType.attrString:
		            typeTemp[0] = new AttrType(AttrType.attrString);
		            temp.setHdr((short)1, typeTemp, new short[]{REC_LEN_STRING});
		            
		            String strVal = temp.getStrFld(1);
					tuple.setStrFld(i+1, strVal);
					break;
			}
		}

		return tuple;
	}
	
    /** Position the scan cursor to the Tuple with the given tid.
     * 
     * @exception InvalidTupleSizeException Invalid tuple size
     * @exception IOException I/O errors
     * @param tid Tuple ID of the given record
     * @return 	true if successful, 
     *			false otherwise.
     */
	public boolean position(TID tid)
		    throws InvalidTupleSizeException,
			   IOException
	{ 
		boolean status = false;
		
		for(int i = 0; i<_numCols;i++)
		{
			status = _hfScans[i].position(tid.recordIDs[i]);
		}
		    
		return status;
	}
	
	
	/** Closes the TupleScan object */
	public void closeTuplescan()
	{
		for(int i = 0; i<_numCols;i++)
		{
			_hfScans[i].closescan();
			_hfScans[i] = null;
		}
		_numCols = 0;
		_cf = null;
		_hfScans = null;
	}
	   

}//end of TupleScan